package com.morningstar.system.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.morningstar.common.dao.entity.CommonQuery;
import com.morningstar.common.result.Result;
import com.morningstar.common.result.ServiceCheckResult;
import com.morningstar.system.dao.entity.SysDept;
import com.morningstar.system.dao.entity.SysUser;
import com.morningstar.system.service.SysDeptService;
import com.morningstar.system.service.SysUserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.morningstar.common.constants.permission.PermissionConstants.*;

/**
 * 部门信息接口
 *
 * @author yanglianshan
 */
@Slf4j
@RestController
@RequestMapping("/system/dept")
public class SysDeptController {

    private static final String PERMISSION = "system.dept";
    private static final String PERMISSION_LIST = PERMISSION + LIST;
    private static final String PERMISSION_DETAIL = PERMISSION + DETAIL;
    private static final String PERMISSION_UPDATE = PERMISSION + UPDATE;
    private static final String PERMISSION_ADD = PERMISSION + ADD;
    private static final String PERMISSION_DELETE = PERMISSION + DELETE;

    private static final Long ROOT_DEPT_ID = 0L;

    @Resource
    private SysDeptService deptService;

    @Resource
    private SysUserService userService;

    /**
     * 获取部门树
     *
     * @param hasRoot 是否有根节点
     * @return 部门树
     */
    @GetMapping(value = "/tree")
    @SaCheckLogin
    public Result<Object> select(@RequestParam("hasRoot") Boolean hasRoot) {
        List<SysDept> depts = deptService.list();
        List<SysDept> result = new ArrayList<>();
        List<Long> rootIds = new ArrayList<>();
        rootIds.add(ROOT_DEPT_ID);
        if (hasRoot) {
            SysDept root = new SysDept();
            root.setDeptId(ROOT_DEPT_ID);
            root.setDeptName("根节点");
            root.setChildren(this.buildDeptTree(rootIds, depts));
            result.add(root);
        } else {
            result = this.buildDeptTree(rootIds, depts);
        }
        return Result.successData(result);
    }

    /**
     * 部门树列表
     *
     * @param commonQuery 通用查询类
     * @return 部门列表
     */
    @PostMapping(value = "/list")
    @SaCheckPermission(PERMISSION_LIST)
    public Result<List<SysDept>> list(@RequestBody CommonQuery<SysDept, SysDept> commonQuery) {
        SysDept query = commonQuery.getQuery();
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper<>();
        if (query != null) {
            queryWrapper.like(StringUtils.isNotBlank(query.getDeptName()), SysDept::getDeptName, query.getDeptName());
        }
        List<SysDept> depts = deptService.list(queryWrapper);
        Map<Long, List<SysUser>> userMap = userService.list().stream().collect(Collectors.groupingBy(SysUser::getUserId));
        depts.forEach(item -> {
            if (userMap.containsKey(item.getLeader())) {
                SysUser sysUser = userMap.get(item.getLeader()).get(0);
                item.setLeaderName(sysUser.getUserName());
                item.setEmail(sysUser.getEmail());
                item.setPhone(sysUser.getPhone());
            }
        });
        List<Long> parentIds = depts.stream().map(SysDept::getParentId).toList();
        List<Long> deptIds = depts.stream().map(SysDept::getDeptId).toList();
        List<Long> rootIds = parentIds.stream().filter(item -> !deptIds.contains(item)).toList();
        return Result.successData(this.buildDeptTree(rootIds, depts));
    }

    /**
     * 新增部门
     *
     * @param sysDept 部门信息
     * @return 响应结果
     */
    @PostMapping
    @SaCheckPermission(PERMISSION_ADD)
    public Result<Object> add(@RequestBody SysDept sysDept) {
        ServiceCheckResult checkResult = deptService.checkAddAndUpdate(sysDept);
        if (checkResult.isResult()) {
            return Result.fail(checkResult.getMessage());
        }
        deptService.save(sysDept);
        return Result.successNoData();
    }

    /**
     * 更新部门
     *
     * @param sysDept 部门信息
     * @return 响应结果
     */
    @PostMapping(value = "/update")
    @SaCheckPermission(PERMISSION_UPDATE)
    public Result<Object> update(@RequestBody SysDept sysDept) {
        ServiceCheckResult checkResult = deptService.checkAddAndUpdate(sysDept);
        if (checkResult.isResult()) {
            return Result.fail(checkResult.getMessage());
        }
        deptService.updateById(sysDept);
        return Result.successNoData();
    }

    /**
     * 部门详情
     *
     * @param deptId 部门Id
     * @return 部门详情
     */
    @GetMapping("/detail")
    @SaCheckPermission(PERMISSION_DETAIL)
    public Result<Object> detail(@RequestParam("deptId") Long deptId) {
        SysDept dept = deptService.getById(deptId);
        SysUser sysUser = userService.getById(dept.getLeader());
        if (sysUser != null) {
            dept.setPhone(sysUser.getPhone());
            dept.setEmail(sysUser.getEmail());
        }
        return Result.successData(deptService.getById(deptId));
    }

    /**
     * 删除部门
     *
     * @param deptId 部门Id
     * @return 响应结果
     */
    @GetMapping("/delete")
    @SaCheckPermission(PERMISSION_DELETE)
    public Result<Object> delete(@RequestParam("deptId") Long deptId) {
        // todo 删除部门校验
        deptService.removeById(deptId);
        return Result.successNoData();
    }

    /**
     * 递归生成部门树
     *
     * @param parentMenuId 根部门Id
     * @param depts        部门列表
     * @return 部门树
     */
    private List<SysDept> buildDeptTree(List<Long> parentDeptIds, List<SysDept> depts) {
        List<SysDept> sysDepts = depts.stream()
                .filter(dept -> parentDeptIds.contains(dept.getParentId()))
                .sorted(Comparator.comparing(SysDept::getOrderNum))
                .toList();
        List<SysDept> result = new ArrayList<>();
        if (CollectionUtil.isEmpty(sysDepts)) {
            return null;
        }
        for (SysDept sysDept : sysDepts) {
            List<Long> deptIds = new ArrayList<>();
            deptIds.add(sysDept.getDeptId());
            sysDept.setChildren(this.buildDeptTree(deptIds, depts));
            result.add(sysDept);
        }
        return result;
    }
}
